﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace BarcodePrint
{
    public partial class FrmMain : Form
    {
        public FrmMain()
        {
            InitializeComponent();
        }

        private DeviceType deviceType = DeviceType.DRV;
        private string printParam = "1";
        private readonly PrinterProgramLanguage printerProgramLanguage = PrinterProgramLanguage.ZPL;

        /// <summary>
        /// 打印机设置
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void printSetup_Click(object sender, EventArgs e)
        {
            frmSetupPrinter frmSetupPrinter = new frmSetupPrinter();
            if (frmSetupPrinter.ShowDialog() == DialogResult.OK)
            {
                this.deviceType = frmSetupPrinter.deviceType;
            }
        }

        #region 打印

        /// <summary>
        /// 打印
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>

        private void btnPrint_Click(object sender, EventArgs e)
        {
            this.BarcodeOperateBatch("hello word");
        }

        private void BarcodeOperateBatch(string body)
        {
            if (printerProgramLanguage == PrinterProgramLanguage.EPL)
            {
                PrintUtil.Print(string.Format("Q{0}\r\n", body), deviceType, printParam);
            }
            else
            {
                PrintUtil.Print(string.Format("Q{0}\r\n", body), deviceType, printParam);
            }

            ReleaseMemory();
        }

        public static void ReleaseMemory()
        {
            GC.Collect();
            GC.WaitForPendingFinalizers();
            if (Environment.OSVersion.Platform == PlatformID.Win32NT)
            {
                SetProcessWorkingSetSize(Process.GetCurrentProcess().Handle, -1, -1);
            }
        }
        [DllImport("kernel32.dll", EntryPoint = "SetProcessWorkingSetSize")]
        public static extern int SetProcessWorkingSetSize(IntPtr process, int minSize, int maxSize);

        #endregion

        #region Http服务器

        private HttpListener listener;
        private void FrmMain_Load(object sender, EventArgs e)
        {
            Thread thread = new Thread(() =>
            {
                StartHttpServer();
            });
            thread.Start();
        }

        void StartHttpServer()
        {
            try
            {
                listener = new HttpListener();
                listener.AuthenticationSchemes = AuthenticationSchemes.Anonymous;
                listener.Prefixes.Add("http://127.0.0.1:8081/api/print/");
                listener.Start();
            }
            catch (Exception ex)
            {
                Log("服务器启动失败......");
            }

            int minThreadNum; int portThreadNum; int maxThreadNum;
            ThreadPool.GetMinThreads(out minThreadNum, out portThreadNum);
            ThreadPool.GetMaxThreads(out maxThreadNum, out portThreadNum);

            Log("最大线程数" + maxThreadNum);
            Log("最小空闲线程数" + minThreadNum);
            Log("服务器启动成功，等待客户连接中......");

            while (true)
            {//等待请求连接//没有请求则GetContext处于阻塞状态

                HttpListenerContext httpListenerContext = listener.GetContext();
                ThreadPool.QueueUserWorkItem(new WaitCallback(TaskProc), httpListenerContext);
            }
        }


        void TaskProc(object obj)
        {
            HttpListenerContext ctx = (HttpListenerContext)obj;
            ctx.Response.StatusCode = 200;//设置返回给客服端http状态代码//接收POST参数
            Stream stream = ctx.Request.InputStream;
            StreamReader reader = new StreamReader(stream, Encoding.UTF8);
            string body = reader.ReadToEnd();

            Log("收到HTTP数据：\r\n" + body);


            Log("根据业务处理执行打印任务......");
            BarcodeOperateBatch(body);

            //使用Writer输出http响应代码,UTF8格式
            var replyMsg = new ApiResult<bool>()
            {
                Code = 200,
                Data = true,
                Msg = "打印成功"
            };

            using (StreamWriter writer = new StreamWriter(ctx.Response.OutputStream, Encoding.UTF8))
            {
                writer.Write(replyMsg);
                writer.Close();
                ctx.Response.Close();
            }

            Log("打印完毕,返回打印结果");
        }

        private void FrmMain_FormClosed(object sender, FormClosedEventArgs e)
        {
            listener?.Stop();
        }

        void Log(string msg)
        {
            this.Invoke(new Action(() =>
            {
                richTxt.AppendText(DateTime.Now.ToString("yyyy-MM-dd hh:MM:ss") + msg + Environment.NewLine);
            }));
        }

        #endregion
    }

    public class ApiResult<T>
    {
        public int Code { get; set; }
        public string Msg { get; set; }
        public T Data { get; set; }
    }
}
